/** 
 * The control class for the paver program.
 * Or really this is the paver program.
 * For 2nd Pro Software Project in ENEL323 by Brian Thorne & Hamish Cumming 2008.
 * Released under GPLv3
 * Project Homepage: http://code.google.com/p/mega8-hob/
 * 
 * @file paver.cpp
 * @see http://code.google.com/p/mega8-hob/source/browse/trunk/paver.cpp
 * @author Hamish Cumming & Brian Thorne
 * @version see SVN revision number
 */

#include "atto.h"
#include "paver.h"
#include "button.h"
#include "linked_list.h"
#include <stdlib.h>
#include <stdio.h>
#include "polygon.h"
#include <math.h>
#include "pavingstone.h"

/// Set the debug level here.
/// For development it should be CHECK_DEBUG_LEVEL.
#define DEBUG_LEVEL CHECK_DEBUG_LEVEL

/* Type definitions */

/** Canvas type for drawing area to be paved. */
typedef struct {
    int height;             /* Height of canvas */
    int width;              /* Width of canvas */
    int top;                /* y location of canvas */
    int left;               /* x location of canvas */
    linked_list_t * ll;     /* A doubly linked list, for the points of a polygon */
} canvas_t;

/* Prototypes for local functions */
void update_colours();
int mouse_in_any_button (int mouse_x, int mouse_y);
int mouse_in_button (int mouse_x, int mouse_y, button_t *button);
button_t * make_button_set (void);
void draw_button_set (void);
void draw_button (button_t *button);
int mouse_in_canvas (int mouse_x, int mouse_y, canvas_t * canvas);
point_t * create_point(int x, int y);
vector_t rotate_vector(vector_t vector, float angle);
void draw_segment(segment_t segment);
void redrawonce();
        
/* Constants */
enum window_dims {WIN_WIDTH = 900, WIN_HEIGHT = 600};

enum button_set {
BUT1_TOP = 10, BUT1_LEFT = 610, BUT1_H = 30, BUT1_W = 130,
BUT2_TOP = 50, BUT2_LEFT = 610, BUT2_H = 30, BUT2_W = 180,
BUT3_TOP = 90, BUT3_LEFT = 610, BUT3_H = 30, BUT3_W = 180,
BUT4_TOP = 550, BUT4_LEFT = 800, BUT4_H = 30, BUT4_W = 80,
BUT5_TOP = 550, BUT5_LEFT = 740, BUT5_H = 30, BUT5_W = 20,
BUT6_TOP = 550, BUT6_LEFT = 770, BUT6_H = 30, BUT6_W = 20,
BUT7_TOP = 10, BUT7_LEFT = 750, BUT7_H = 30, BUT7_W = 140,

BUT8_TOP = 160, BUT8_LEFT = 620,BUT8_H = 50, BUT8_W = 50,
BUT9_TOP = 160, BUT9_LEFT = 740,BUT9_H = 38, BUT9_W = 31,
BUT10_TOP = 160, BUT10_LEFT = 840,BUT10_H = 33, BUT10_W = 16,

BUT11_TOP = 420, BUT11_LEFT = 610,BUT11_H = 30, BUT11_W = 30, //Colors
BUT12_TOP = 420, BUT12_LEFT = 650,BUT12_H = 30, BUT12_W = 30,
BUT13_TOP = 420, BUT13_LEFT = 690,BUT13_H = 30, BUT13_W = 30,
BUT14_TOP = 420, BUT14_LEFT = 730,BUT14_H = 30, BUT14_W = 30,

BUT15_TOP = 260,BUT15_LEFT = 610,BUT15_H = 85,BUT15_W = 85,
BUT16_TOP = 260,BUT16_LEFT = 710,BUT16_H = 85,BUT16_W = 85,
BUT17_TOP = 260,BUT17_LEFT = 810,BUT17_H = 85,BUT17_W = 85,

NUM_BUTS = 16};

static char * BUT1_LABEL = "Add Point";
static char * BUT2_LABEL = "Select Lay Line";
static char * BUT4_LABEL = "Reset";
static char * BUT5_LABEL = "+";
static char * BUT6_LABEL = "-";
static char * BUT7_LABEL = "Remove Point";
static char * BUT8_LABEL = "";  // Patio
static char * BUT9_LABEL = "";  // Cobblestone
static char * BUT10_LABEL = ""; // London
static char * BUT11_LABEL = ""; // Grey
static char * BUT12_LABEL = ""; // Charcoal
static char * BUT13_LABEL = ""; // Brown
static char * BUT14_LABEL = ""; // Marble
static char * BUT15_LABEL = ""; // style1
static char * BUT16_LABEL = ""; // style2
static char * BUT17_LABEL = ""; // style3
/* The border for canvas, button areas */
#define BORDER_WIDTH 2
/* Constants for the preview layouts */
#define PREV1_L 640
#define PREV2_L 740
#define PREV3_L 840
#define PREV_T 290
#define PREV_W 25
#define PREV_H 35

/* Globals to file */

static colour_t background_colour = lightgrey;
static colour_t border = black;
static point_t dbg_point = {0, 0};
static int click_mode = 0;
static button_t * button_table = NULL;	// Pointer to array of button_t structures
static canvas_t canvas = {600, 600, 0, 0, NULL};
static pavingpattern_t pattern, style1,style2,style3;
static int drawnyet = 0;
/* These two variables are set when the mouse is pressed down on either a button or canvas */
static int  selected_button;
static canvas_t * selected_canvas;
static segment_t selected_segment;
static float scale = 0.3;

/* The preview polygons */
linked_list_t * poly1 = linked_list_create();
linked_list_t * poly2 = linked_list_create();
linked_list_t * poly3 = linked_list_create();

/* determines what the action is for a canvas click */
/* Mostly useful for debugging */
enum BUT_MODE {
ADD_POINT = 0,
SELECT_LINE = 1, 
PNT_ON_PGON = 2, 
PNT_IN_PGON = 3};


/**
 * Update colours. Are the colours shown correct for the brick type selected? 
 */
void update_colours()
{
    int but_index,i;
    button_t * button;
    Assert (button_table != NULL);  /* Buttons should be initialised on startup */
    but_index = 9;
    
    for(i=but_index;i<but_index+4;i++)
    {
        button = &button_table[i];
        if(i==but_index && !pattern.stone.grey  )
        {
            button->state = BUT_INVIS;
        } else if(i==but_index+1 && !pattern.stone.charcoal  )
        {
            button->state = BUT_INVIS;
        } else if(i==but_index+2 && !pattern.stone.brown  )
        {
            button->state = BUT_INVIS;
        } else if(i==but_index+3 && !pattern.stone.marble  )
        {
            button->state = BUT_INVIS;
        } else if(button->state == BUT_INVIS )
        {
            button->state = BUT_OUT;
        }
    }
}


/**
 * Add Point selected. 
 */
void button_0_click()
{
    click_mode = 0;
}

/**
 * Select line selected
 */
void button_1_click()
{
    click_mode = 1;
}
/**
 * Reset everything. Clear canvas and reset everything that may have been changed.
 */
void reset()
{
    while (canvas.ll->start_node != NULL)
    {
        delete_node(canvas.ll,canvas.ll->start_node);
    }
    selected_segment.start.x = selected_segment.start.y = -1;
    click_mode = 0;
    scale = 0.3;
    pattern = style1;
}

/**
 * Increase Scale
 */
void button_4_click()
{
    if (scale < 0.1)
        scale += 0.01;
    else
    {
        if (scale < 1.0)
            scale += 0.1;
    }
}

/**
 * Decrease Scale
 */
void button_3_click()
{
    if (scale > 0.2)
        scale -= 0.1;
    else
    {
        if (scale > 0.06)
            scale -= 0.01;
        else
            return;
    }
}

/**
 * Delete last point
 */
void button_5_click()
{
    if (canvas.ll->nodes != 0)
        delete_node(canvas.ll,canvas.ll->end_node);
    selected_segment.start.x = selected_segment.start.y = -1; //in case our selected segment was part of a deleted node
}

void button_6_click(){}
void button_7_click(){}

/**
 * Patio pavingstone selected.
*/
void button_8_click()
{
    pattern = pavingunit7;
}

/**
 * Cobblestone pavingstone selected.
*/
void button_9_click()
{
    pattern = pavingunit1;
}

/**
 * London pavingstone selected.
*/
void button_10_click()
{
    pattern = pavingunit4;
}



/**
 * Grey Button
 */
void select_grey()
{
    pattern.stone.colour = grey;
}

/**
 * Charcoal Button
 */
void select_charcoal()
{
    pattern.stone.colour = charcoal;
}

/**
 * Brown Button
 */
void select_brown()
{
    pattern.stone.colour = brown;
}

/**
 * Marble Button
 */
void select_marble()
{
    pattern.stone.colour = marble;
}

/**
 * The first Style shown is selected
*/
void style1_selected()
{
    colour_t c = pattern.stone.colour; //Need to save colour in case user has allready made that customization.
    pattern=style1;
    pattern.stone.colour = c;
}

/**
 * Second style shown selected
 */
void style2_selected()
{
    colour_t c = pattern.stone.colour;
    pattern=style2;
    pattern.stone.colour = c;
}

/**
 * Third style (if shown)
 * has been selected.
 */
void style3_selected()
{
    colour_t c = pattern.stone.colour;
    pattern=style3;
    pattern.stone.colour = c;
}


/**
 * Handle a click within the main pavement area canvas.
 */ 
void canvas_click()
{
    switch (click_mode)
    {
    case ADD_POINT:
        atto_get_mouse(&dbg_point.x, &dbg_point.y);
        if (!pnt_intersects_pgon(canvas.ll, dbg_point))
        {
            add_node(canvas.ll, create_point(dbg_point.x, dbg_point.y));
            selected_segment.start.x = selected_segment.start.y = -1;
        }
        break;
    case PNT_ON_PGON:
        atto_get_mouse(&dbg_point.x, &dbg_point.y);
        if (pnt_on_pgon (canvas.ll, dbg_point))
            atto_message("Point is  on Polygon");
        else
            atto_message ("Point is not on polygon");
        break;
    case SELECT_LINE:
        if (pgon_close(canvas.ll) == 0)
            return;
        atto_get_mouse(&dbg_point.x, &dbg_point.y);
        if (pnt_on_pgon (canvas.ll, dbg_point))
            selected_segment = pnt_on_pgon_segment(canvas.ll, dbg_point);
        break;
    case PNT_IN_PGON:
        atto_get_mouse(&dbg_point.x, &dbg_point.y);
        if (!pnt_outside_pgon (canvas.ll, dbg_point))
            atto_message("point in polygon");
        else
            atto_message("point not in polygon");
        break;
    default:
        break;
    }
}

/**
 * Handles any keyboard presses. Could get each button to have a shortcut key.
 * @param code The key pressed.
 */
void key(int code)
{
}

/** handle a mouse depression. Check if the button is out and has been clicked
 * @param x The x coordinate where the mouse was pressed
 * @param y The y coordinate where the mouse was pressed.
 * @param mouse_but The mouse button that was pressed.
 */
void mouse_down(int x, int y, int mouse_but)
{
    /* Handle Buttons */
    selected_button = -1;
    int but_index;
    button_t * button;
    Assert (button_table != NULL);  /* Buttons should be initialised on startup */
    but_index = mouse_in_any_button (x, y);
    button = &button_table[but_index];
    if (but_index > -1 && get_button_state (button) == BUT_OUT)
    {
        if (button->state == BUT_INVIS)
            return;
        selected_button = but_index;
        change_button_state (button);   // add second param MOUSE_DOWN, set mouse 
        atto_redraw ( );	        // Make sure a draw() call is made
        return;                         // should be no need to continue
    }
    /* Handle Canvas */
    if (mouse_in_canvas(x, y, &canvas))
    {
        selected_canvas = &canvas;
    }
}

/** Handles mouse dragging.
 * @param x The x coordinate where the mouse is.
 * @param y The y coordinate where the mouse is.
 * @param mouse_but The mouse button that is being held.
 */
void mouse_drag(int x, int y, int mouse_but)
{
    /* Handle Buttons */
    if ((selected_button >= 0)) /*Least we get a segmentation fault.... */
    {
        if  ((mouse_in_button (x, y, &button_table[selected_button]) && get_button_state (&button_table[selected_button]) == BUT_OUT)
            || (!mouse_in_button (x, y, &button_table[selected_button]) && get_button_state (&button_table[selected_button]) == BUT_IN))
        {
            change_button_state (&button_table[selected_button]);
            atto_redraw ( );	// Make sure a draw() call is made
        }
    }
    /* Handle Canvas */
    if (selected_canvas >= 0)
    {
        //draw temp point if inside canvas

    }
}

/** Handles mouse releases. Initiates the functions attached to each button.
 * @param x The x coordinate where the mouse was released.
 * @param y The y coordinate where the mouse was released.
 * @param mouse_but The mouse button that was released.
 */
void mouse_up(int x, int y, int mouse_but) 
{
    /* Handle buttons */
    if (selected_button >= 0)
    {
        Assert (button_table != NULL);  /* Buttons should be initialised on startup */
        if (mouse_in_button(x, y, &button_table[selected_button]))
        {
            change_button_state (&button_table[selected_button]);
            (&button_table[selected_button])->action(); // Call the function pointed to by the button struct found in the button table. 
            atto_redraw ( );	// Make sure a draw() call is made	  
        }
        selected_button = -1;
    }

    /* Handle Canvas */
    if (selected_canvas != NULL)
    {
        if (mouse_in_canvas(x, y, &canvas))
        {
            canvas_click();
            atto_redraw ( );
        }
        selected_canvas = NULL;
    }
}


/** 
 * Master drawing function called by atto.
 * Calls all other draw functions.
 */
void draw()
{
    /** Draw background */
    atto_color (border.r, border.g, border.b);
    atto_fill (0, 0, WIN_WIDTH, WIN_HEIGHT);
    
    /** Draw Canvas */
    atto_color (background_colour.r, background_colour.g, background_colour.b);
    atto_fill (BORDER_WIDTH, BORDER_WIDTH, canvas.width - 2*BORDER_WIDTH, canvas.height - 2*BORDER_WIDTH);
    atto_fill (canvas.width + BORDER_WIDTH, BORDER_WIDTH, WIN_WIDTH - canvas.width - 2*BORDER_WIDTH, WIN_HEIGHT - 2*BORDER_WIDTH);
    
    /** Draw Square Grid of dashes */
    atto_color (black.r, black.g, black.b);
    int rows = 10; /* This will be changed to be adjustable? */
    int gap = (canvas.height - 4 * BORDER_WIDTH)/(rows+1);
    int dash_length = 4;
    int row, col;
    for(col=0;col<rows;col++)
    {
        for(row=1;row<=rows;row++)
        {
            atto_line(BORDER_WIDTH + gap + col*gap,BORDER_WIDTH + row*gap,BORDER_WIDTH + gap + dash_length + col*gap,BORDER_WIDTH + row*gap);
        }
    }


    /** Draw Points */
    if (canvas.ll->start_node != NULL)
    {
        list_node * node;
        node = canvas.ll->start_node;
        atto_fill(node->point->x - 2, node->point->y - 2, 4, 4);
        while (node->next != NULL)
        {
            point_t * point = node->point;
            point_t * nextpoint = node->next->point;
            atto_line(point->x, point->y, nextpoint->x, nextpoint->y);
            node = node->next;
            atto_fill(node->point->x - 2, node->point->y - 2, 4, 4);
        }
        //draw last segment if possible
        if (pgon_close(canvas.ll))
        {
            atto_color(red.r,red.g,red.b);
            atto_line(canvas.ll->end_node->point->x, canvas.ll->end_node->point->y, canvas.ll->start_node->point->x, canvas.ll->start_node->point->y);
        }
    }
    /* draw selected segment */
    if (!((selected_segment.start.x == -1) && (selected_segment.start.y == -1)))
    {
        atto_color (blue.r, blue.g, blue.b);
        atto_line(selected_segment.start.x, selected_segment.start.y, selected_segment.end.x, selected_segment.end.y);
    }
    /** draw the paving stones */
    int number_stones = 0;
    int number_stones_cut = 0;
    if (pgon_close(canvas.ll) && selected_segment.start.x != -1 && selected_segment.start.y != -1)
    {

        number_stones = lay_pavingstones(canvas.ll, selected_segment, scale_pattern(pattern,scale), &number_stones_cut);
    }

    /** Draw button bg (do this again in case bricks went over it) */
    atto_color (background_colour.r, background_colour.g, background_colour.b);
    atto_fill (canvas.width + BORDER_WIDTH, BORDER_WIDTH, WIN_WIDTH - canvas.width - 2*BORDER_WIDTH, WIN_HEIGHT - 2*BORDER_WIDTH);
    
    /** Draw the buttons */
    update_colours();
    if (button_table != NULL)
        draw_button_set ();

    /** Draw the Selection Stones */
    atto_string (BUT1_LEFT, BUT13_TOP - 20, "Select Colour:");
    char str[20];
    sprintf(str, "Select Pavestone:");
    atto_string(BUT1_LEFT,150 ,str);
   
    /** Draw the Pavement Type Selection */
    char str_pt[20];
    sprintf(str_pt, "Select Paving Scheme:");
    atto_color(black.r, black.g, black.b);
    atto_string(BUT1_LEFT,250 ,str_pt);

    segment_t seg1;
    segment_t seg2;
    segment_t seg3;

    seg1.start = *poly1->start_node->point;
    seg1.end = *poly1->start_node->next->point;
    seg2.start = *poly2->start_node->point;
    seg2.end = *poly2->start_node->next->point;
    seg3.start = *poly3->start_node->point;
    seg3.end = *poly3->start_node->next->point;

    int i;
    float fscale;
    if (strcmp(pattern.stone.name,"London") == 0)
    {
        fscale = 0.1;
        lay_pavingstones(poly1, seg1, scale_pattern(pavingunit4, fscale), &i);
        style1=pavingunit4;
        lay_pavingstones(poly2, seg2, scale_pattern(pavingunit5, fscale), &i);
        style2=pavingunit5;
        lay_pavingstones(poly3, seg3, scale_pattern(pavingunit6, fscale), &i);
        style3=pavingunit6;
        if(button_table[15].state==BUT_INVIS)button_table[15].state=BUT_OUT;redrawonce();
    }
    if(strcmp(pattern.stone.name,"Patio") == 0)
    {
        fscale = 0.08;
        lay_pavingstones(poly1, seg1, scale_pattern(pavingunit7, fscale), &i);
        style1=pavingunit7;
        lay_pavingstones(poly2, seg2, scale_pattern(pavingunit8, fscale), &i);
        style2=pavingunit8;
        button_table[15].state=BUT_INVIS;redrawonce();
    }
    if (strcmp(pattern.stone.name,"Cobblestone") == 0)
    {
        fscale = 0.08;
        lay_pavingstones(poly1, seg1, scale_pattern(pavingunit1, fscale), &i);
        style1=pavingunit1;
        lay_pavingstones(poly2, seg2, scale_pattern(pavingunit2, fscale), &i);
        style2=pavingunit2;
        lay_pavingstones(poly3, seg3, scale_pattern(pavingunit3, fscale), &i);
        style3=pavingunit3;
        if(button_table[15].state==BUT_INVIS)button_table[15].state=BUT_OUT;redrawonce();
    }

    /** Draw brick results */
    char s[35];
    atto_color(black.r, black.g, black.b);
    sprintf(s, "Number of stones:%d",number_stones);
    atto_string(610,470,s);
    sprintf(s, "Number that need cutting:%d", number_stones_cut);
    atto_string(610,490,s);

    /** Draw scale bit */
    atto_color(black.r, black.g, black.b);
    char string_scale[30];
    sprintf(string_scale,"Scale: %.2dmm per division",(int)(gap/scale));
    atto_string(BUT1_LEFT,BUT5_TOP - 10 ,string_scale);
}
/**
 * Redraw
 */
void redrawonce()
{
    if(!drawnyet){ drawnyet=1;draw();}
    else drawnyet=0;
}

/* Implementations of local functions */

/** Initialises button table.
 *  Should be called once only. #buttons and characteristics are defined
 *  in the function.
 * @see button.h
 * @return pointer to array of buttons or NULL if memory allocation fails. 
 */
button_t *make_button_set (void)
{
   button_t *button_table;

   button_table = (button_t *) malloc (NUM_BUTS * sizeof(button_t));
   if (button_table != NULL)
   {
       /* make_button (top,left,h,w,label,action,c_in,c_out,c_edge_in, c_edge_out) */
        /** Make all the buttons */
        button_table[0] = make_button (BUT1_TOP, BUT1_LEFT, BUT1_H, BUT1_W, BUT1_LABEL, button_0_click,blue,red,green,black);
        button_table[1] = make_button (BUT2_TOP, BUT2_LEFT, BUT2_H, BUT2_W, BUT2_LABEL, button_1_click,blue,red,green,black);
        button_table[2] = make_button (BUT4_TOP, BUT4_LEFT, BUT4_H, BUT4_W, BUT4_LABEL, reset,blue,red,green,black);
        button_table[3] = make_button (BUT5_TOP, BUT5_LEFT, BUT5_H, BUT5_W, BUT5_LABEL, button_3_click,blue,red,green,black);
        button_table[4] = make_button (BUT6_TOP, BUT6_LEFT, BUT6_H, BUT6_W, BUT6_LABEL, button_4_click,blue,red,green,black);
        button_table[5] = make_button (BUT7_TOP, BUT7_LEFT, BUT7_H, BUT7_W, BUT7_LABEL, button_5_click,blue,red,green,black);
        button_table[6] = make_button (BUT8_TOP, BUT8_LEFT, BUT8_H, BUT8_W, BUT8_LABEL, button_8_click,black,grey,green,black);
        button_table[7] = make_button (BUT9_TOP, BUT9_LEFT, BUT9_H, BUT9_W, BUT9_LABEL, button_9_click,black,grey,green,black);
        button_table[8] = make_button (BUT10_TOP, BUT10_LEFT, BUT10_H, BUT10_W, BUT10_LABEL, button_10_click,black,grey,green,black);
        
        button_table[9] = make_button (BUT11_TOP, BUT11_LEFT, BUT11_H, BUT11_W, BUT11_LABEL, select_grey,grey,grey,green,black);
        button_table[10] = make_button (BUT12_TOP, BUT12_LEFT, BUT12_H, BUT12_W, BUT12_LABEL, select_charcoal,charcoal,charcoal,green,black);
        button_table[11] = make_button (BUT13_TOP, BUT13_LEFT, BUT13_H, BUT13_W, BUT13_LABEL, select_brown,brown,brown,green,black);
        button_table[12] = make_button (BUT14_TOP, BUT14_LEFT, BUT14_H, BUT14_W, BUT14_LABEL, select_marble,marble,marble,green,black);
        button_table[13] = make_button (BUT15_TOP, BUT15_LEFT, BUT15_H, BUT15_W, BUT15_LABEL, style1_selected,lightgrey,lightgrey,green,black);
        button_table[14] = make_button (BUT16_TOP, BUT16_LEFT, BUT16_H, BUT16_W, BUT16_LABEL, style2_selected,lightgrey,lightgrey,green,black);
        button_table[15] = make_button (BUT17_TOP, BUT17_LEFT, BUT17_H, BUT17_W, BUT17_LABEL, style3_selected,lightgrey,lightgrey,green,black);
        
   }
   return button_table;
}

/**
 * Is the mouse inside a button?
 * @param mouse_x The x coord of the mouse.
 * @param mouse_y The y coord of the mouse.
 * @return index of button, or -1 if not in button.
 */
int mouse_in_any_button (int mouse_x, int mouse_y)
{
   int but_index;
   
   for (but_index = 0; but_index < NUM_BUTS; but_index++)
   {
      if (mouse_in_button (mouse_x, mouse_y, &button_table[but_index]))
         return but_index;
   }
   return -1;
}

/**
 * Is the mouse within a particular canvas?
 * @param mouse_x The x coordinate of the mouse.
 * @param mouse_y The y coordinate of the mouse.
 * @return boolean answer.
 */
int mouse_in_canvas (int mouse_x, int mouse_y, canvas_t * canvas)
{
    Assert (canvas != NULL);  /* canvas should be initialised on startup */
    return (mouse_x >= canvas->left && mouse_x <= canvas->left + canvas->width 
        && mouse_y >= canvas->top  && mouse_y <= canvas->top  + canvas->height);
}

/**
 * Draw all buttons in the button set.
 */
void draw_button_set (void)
{
   int but_index;
   
   for (but_index = 0; but_index < NUM_BUTS; but_index++)
   {
      draw_button (&button_table[but_index]);
   }
}

/**
 * initialse everything thats needs to be run once.
 */
int initialise(void)
{
    /* Initialise buttons */
    if ((button_table = make_button_set ()) == NULL)
    {
        fprintf (stderr, "Memory allocation error");
        return 1;
    }
    
    
    /* Initialise linked list */
    canvas.ll = linked_list_create();
    selected_segment.start.x = selected_segment.start.y = -1;

    /* Initialise the preview areas */
    point_t * poly1p1 = create_point(PREV1_L, PREV_T);
    point_t * poly1p2 = create_point(PREV1_L + PREV_W, PREV_T);
    point_t * poly1p3 = create_point(PREV1_L + PREV_W, PREV_T + PREV_H);
    point_t * poly1p4 = create_point(PREV1_L, PREV_T + PREV_H);
    point_t * poly2p1 = create_point(PREV2_L, PREV_T);
    point_t * poly2p2 = create_point(PREV2_L + PREV_W, PREV_T);
    point_t * poly2p3 = create_point(PREV2_L + PREV_W, PREV_T + PREV_H);
    point_t * poly2p4 = create_point(PREV2_L, PREV_T + PREV_H);
    point_t * poly3p1 = create_point(PREV3_L, PREV_T);
    point_t * poly3p2 = create_point(PREV3_L + PREV_W, PREV_T);
    point_t * poly3p3 = create_point(PREV3_L + PREV_W, PREV_T + PREV_H);
    point_t * poly3p4 = create_point(PREV3_L, PREV_T + PREV_H);

    add_node (poly1, poly1p1);
    add_node (poly1, poly1p2);
    add_node (poly1, poly1p3);
    add_node (poly1, poly1p4);
    add_node (poly2, poly2p1);
    add_node (poly2, poly2p2);
    add_node (poly2, poly2p3);
    add_node (poly2, poly2p4);
    add_node (poly3, poly3p1);
    add_node (poly3, poly3p2);
    add_node (poly3, poly3p3);
    add_node (poly3, poly3p4);

    pattern = pavingunit2; //default pattern
    return EXIT_SUCCESS;
}

/**
 * The entry point, handle setting up, then hand over control to the system via atto.
 */
int main(int argc, char **argv)
{
    initialise();
    atto_setup(WIN_WIDTH, WIN_HEIGHT, key, mouse_down, mouse_drag, mouse_up, draw);
    atto_main(argc, argv); // Hand over control to atto 
}

/**
 * Create an object of type point.
 * @param x Coordinate of point.
 * @param y Coordinate of point.
 * @return The point created.
 */
point_t * create_point(int x, int y)
{
    point_t * point;
    if((point = (point_t * )malloc(sizeof(point_t))) == NULL) return NULL;
    point->x = x;
    point->y = y;
    return point;
}
